The increasing use of computing devices in all manner of tasks including handling of commercially valuable or personally identifiable information, performing important financial transactions, and controlling dissemination of confidential information has made the ability to secure computing devices against attacks to steal information and/or to more generally take control of them ever more important. Over time, as attack techniques have continued to evolve, so have techniques to thwart attacks.
For a number of years, vulnerabilities in the manner in which the call stack (also known as the execution stack or control stack) maintained by the processor components of many computing devices were a focus of attacks. Such attacks entailed loading portions of a malicious routine into pages of a storage of a computing device, and then overwriting a portion of the call stack in what is commonly referred to as a “stack overflow” to cause execution of instructions to jump to the instructions of the malicious routine, thereby taking control of that computing device.
In answer to this type of attack, newer processor components were augmented with the ability to mark individual pages of a storage of a computing device as either “writable” or “executable,” but not both, in a mechanism often referred to as “W-XOR-X.” With such a mechanism in place, portions of a malicious routine might still be stored into pages of a storage marked as “writable,” but once written into those pages, those portions could not be executed due to those pages not being marked “executable.” Thus, even after successfully causing a stack overflow, it was not possible to cause a change in flow of execution to the instructions of the malicious routine.
However, attack techniques have continued to evolve since the widespread introduction of “W-XOR-X” mechanisms in processor components. More recent attacks have focused on examining legitimate routines already stored in pages marked “executable” in computing devices to find portions of those routines that can be combined through a series of jumps to perform functions to gain control of a computing device. Such attacks commonly use library routines that are a frequent component of the operating systems of many computing devices. Library routines tend to be made up of sizable sets of individually callable functions made available to help other routines perform various routine functions. The large size of many of such libraries results in their being a very large number of available functions made up of portions of executable instructions that can be maliciously used if caused to be executed in a particular order.
This type of attack is commonly referred to as return-oriented programming (ROP) due to its reliance on the frequent use of “return” instructions in such legitimate routines to cause jumps among these portions of executable instructions of these library functions by altering the target addresses that are next jumped to by the legitimate return instructions at the end of each of these functions. In effect, a ROP attack uses a computing device's own legitimate library routines against it, thereby circumventing “W-XOR-X” mechanisms by delaying or entirely avoiding the loading of malicious code.